package com.google.code.p.restrpc.http;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class ContentType {

    public static final String ALL_VALUE = "*/*";
    
    public final static String APPLICATION_ATOM_XML_VALUE = "application/atom+xml";
    
    public final static String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";
    
    public final static String APPLICATION_JSON_VALUE = "application/json";
    
    public final static String APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream";
    
    public final static String APPLICATION_XHTML_XML_VALUE = "application/xhtml+xml";
    
    public final static String APPLICATION_XML_VALUE = "application/xml";
    
    public final static String IMAGE_GIF_VALUE = "image/gif";
    
    public final static String IMAGE_JPEG_VALUE = "image/jpeg";
    
    public final static String IMAGE_PNG_VALUE = "image/png";
    
    public final static String MULTIPART_FORM_DATA_VALUE = "multipart/form-data";
    
    public final static String TEXT_HTML_VALUE = "text/html";
    
    public final static String TEXT_PLAIN_VALUE = "text/plain";
    
    public final static String TEXT_XML_VALUE = "text/xml";
    
    public final static String TEXT_JSON_VALUE = "text/json";

    public static ContentType parse(String contentType) {
        StringTokenizer st = new StringTokenizer(contentType, ";");
        List<String> tokens = new ArrayList<String>();
        while (st.hasMoreTokens()) {
            String token = st.nextToken().trim();
            if (token.length() > 0) {
                tokens.add(token);
            }
        }
        
        String[] parts = tokens.toArray(new String[] {});
        
        String mediaType = parts[0].trim();
        
        Map<String, String> parameters = null;
        if (parts.length > 1) {
            parameters = new HashMap<String, String>();
            for (int i = 1; i < parts.length; i++) {
                String parameter = parts[i];
                int indexOfEqual = parameter.indexOf('=');
                if (indexOfEqual != -1) {
                    String attribute = parameter.substring(0, indexOfEqual);
                    String value = parameter.substring(indexOfEqual + 1,
                                                       parameter.length());
                    parameters.put(attribute, value);
                }
            }
        }
        
        return new ContentType(mediaType, parameters);
    }

    private String mediaType;
    
    private Map<String, String> parameters;
    
    public ContentType(String mediaType) {
        super();
        this.mediaType = mediaType;
        this.parameters = new HashMap<String, String>();
    }
    
    public ContentType(String mediaType, Map<String, String> parameters) {
        super();
        this.mediaType = mediaType;
        this.parameters = parameters;
    }

    /**
     * Return a generic parameter value, given a parameter name.
     * @param name the parameter name
     * @return the parameter value; or <code>null</code> if not present
     */
    public String getParameter(String name) {
        return this.parameters.get(name);
    }

    /**
     * Return all generic parameter values.
     * @return a read-only map, possibly empty, never <code>null</code>
     */
    public Map<String, String> getParameters() {
            return parameters;
    }

    /**
     * Return the character set, as indicated by a <code>charset</code> parameter, if any.
     * @return the character set; or <code>null</code> if not available
     */
    public Charset getCharSet() {
        String charSet = getParameter("charset");
        return (charSet != null ? Charset.forName(unquote(charSet)) : null);
    }

    private boolean isQuotedString(String s) {
        return s.length() > 1 && s.startsWith("\"") && s.endsWith("\"") ;
    }

    private String unquote(String s) {
        if (s == null) {
            return null;
        }
        return isQuotedString(s) ? s.substring(1, s.length() - 1) : s;
    }

    public static void main(String[] args) {
        ContentType contentType = ContentType.parse("text/html;charset=utf-8");
        System.out.println(contentType.mediaType);
        System.out.println(contentType.parameters);
    }
}
